#pragma once

#include "Protocol.hpp"
#include "TcpSocket.hpp"
#include "Log.hpp"
#include "UnCopy.hpp"
#include "commen.hpp"
#include "TcpConnectSocket.hpp"
#include "CalculateService.hpp"

const uint16_t default_port = 9090;
const std::string default_ip = "127.0.0.1";

class DlpClient : public UnCopy
{
public:
    DlpClient(std::string server_ip = default_ip, uint16_t server_port = default_port)
        : _server_ip(server_ip), _server_port(server_port)
        , _TcpConnectSocket(server_ip, server_port)
    {
        _factory = std::make_unique<DLP::ReqRespFactory>();
    }

    void start()
    {
        while(true)
        {
            std::string contentByteStream;
            std::cout << ">> ";
            std::getline(std::cin, contentByteStream);

            if(_calculateService.checkInput(contentByteStream) == false) continue;
            int operationPos = _calculateService.getOperationPos(contentByteStream);
            char op = contentByteStream[operationPos];
            int x = std::stoi(contentByteStream.substr(0, operationPos));
            int y = std::stoi(contentByteStream.substr(operationPos + 1));

            std::shared_ptr<DLP::Request> req = _factory->makeRequest(x, y, op);
            std::string dlpRequest = DLP::dlpEncoding(req->serialize()); //序列化

            ssize_t req_n = _TcpConnectSocket.writeStream(dlpRequest);
            if(req_n == 0)
            {
                break;
            }
            else if(req_n < 0)
            {
                _TcpConnectSocket.connect(_server_ip, _server_port);
            }
            else
            {
                std::string dlpResponseStream = "";
                std::string dlpResponseBuffer;
                ssize_t resp_n = _TcpConnectSocket.readStream(dlpResponseBuffer);
                if(resp_n > 0)
                {
                    std::string content;
                    dlpResponseStream += dlpResponseBuffer;
                    while(DLP::dlpDecoding(dlpResponseStream, content)) //反序列化
                    {
                        std::shared_ptr<DLP::Response> resp = std::make_shared<DLP::Response>();
                        bool ret = resp->deserialize(content);
                        if(ret == false)
                        {
                            _calculateService.showResult(-1, -1);
                        }
                        else
                        {
                            int result = resp->getResult();
                            int code = resp->getCode();
                            _calculateService.showResult(result, code);
                        }
                    }
                }
            }
        }
        std::cout << "client quit..." << std::endl;
    }

    ~DlpClient()
    {}
private:
    std::string _server_ip;
    uint16_t _server_port;
    TcpConnectSocket _TcpConnectSocket;
    std::unique_ptr<DLP::ReqRespFactory> _factory;
    CalculateService _calculateService;
};